# file:: game_engine.rb
# author::  Ralph M. Churchill
# version::
# date::
#
# This source code copyright (C) 2006 by Ralph M. Churchill
# All rights reserved.
#
# Released under the terms of the GNU General Public License
# See LICENSE file for additional information.

require 'singleton'
require 'models/game'
require 'engine/game_setup'
require 'engine/game_config'
require 'engine/game_mechanics'

class GameEngine
    include Singleton
    include GameDatabaseSetup,GameConfiguration,GameMechanics

    attr_reader :game

    def startup(options)
        self.root_dir = options.module
        load_command_directories
        load_logic_directories
        @game = load_the_game(self.root_dir)
        @game ||= Game.new
        @game.time ||= Time.now
        @game.running = true
    end
    def shutdown
        @game.running = false
        save_the_game(self.game,self.root_dir)
    end

    def execute_loop
    end

    # Routes actions to the appropriate game mechanics.
    def do_action(action)
        case action.type
        when :enterrealm
            login(action.performer)
        when :leaverealm
            logout(action.performer)
        when :attemptsay
            say(action.performer,action.data[:msg])
        when :attemptlook
            look(action.performer,action.data[:target])
        when :attemptenterportal
            transport({:who => action.performer,
                      :where => action.data[:room],
                      :portal => action.data[:portal]})
        when :attemptgetitem
            give_item({:to => action.performer,
                      :from => action.data[:from],
                      :item => action.data[:item],
                      :quantity => action.data[:quantity]})
        when :attemptdropitem
            give_item({:to => action.data[:into],
                      :from => action.performer,
                      :item => action.data[:item],
                      :quantity => action.data[:quantity]})
        when :command
            return if not action.data[:data] or action.data[:data].empty?
            handle_command(action.performer,action.data[:data])
        when :vision,:sound
            return unless action.performer.respond_to?(:characters)
            action.performer.characters.each{|a| a.do_action(action)}
        when :spawncharacter
            spawn_character(action.data[:character],action.data[:where])
        when :spawnitem
            spawn_item(action.data[:item],action.data[:where])
        else
            action.performer.do_action(action) if action.performer
        end
    rescue UserException => ue
        action.performer.do_action(Action.new(:error,self.performer,
                                              {:msg => ue}))
    rescue => e
        $stderr.puts("GameEngine::do_action Failed: #{e}")
        $stderr.puts(e.backtrace.join("\n"))
    end
    # -------------------------------------------------------------------------
    # Miscellaneous Utility Functions
    # -------------------------------------------------------------------------

    # Load all the command classes into the game's namespace and adds
    # the necessary symbols to the Command Database.
    def load_command_directories #:nodoc:
        require 'util/dir_strings'
        COMMAND_PATH.each do |cmd_dir|
            Dir.glob(cmd_dir/'*.rb') do |cmd|
                load cmd
            end
        end
    end
    def load_logic_directories #:nodoc:
        require 'util/dir_strings'
        LOGIC_PATH.each do |logic_dir|
            Dir.glob(logic_dir/'*.rb') do |logic|
                load logic
            end
        end
    end

end
